package stc.skymobi.netty.handler.codec.memcached.bean.core;

import stc.skymobi.bean.bytebean.ByteBean;
import stc.skymobi.bean.bytebean.annotation.ByteField;
import stc.skymobi.util.IdentifyableOfInt;

/**
 * <pre>Request header
      Byte/     0       |       1       |       2       |       3       |
         /              |               |               |               |
        |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
        +---------------+---------------+---------------+---------------+
       0| Magic         | Opcode        | Key length                    |
        +---------------+---------------+---------------+---------------+
       4| Extras length | Data type     | vbucket id                    |
        +---------------+---------------+---------------+---------------+
       8| Total body length                                             |
        +---------------+---------------+---------------+---------------+
      12| Opaque                                                        |
        +---------------+---------------+---------------+---------------+
      16| CAS                                                           |
        |                                                               |
        +---------------+---------------+---------------+---------------+
        Total 24 bytes

    Response header

     Byte/     0       |       1       |       2       |       3       |
         /              |               |               |               |
        |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
        +---------------+---------------+---------------+---------------+
       0| Magic         | Opcode        | Key Length                    |
        +---------------+---------------+---------------+---------------+
       4| Extras length | Data type     | Status                        |
        +---------------+---------------+---------------+---------------+
       8| Total body length                                             |
        +---------------+---------------+---------------+---------------+
      12| Opaque                                                        |
        +---------------+---------------+---------------+---------------+
      16| CAS                                                           |
        |                                                               |
        +---------------+---------------+---------------+---------------+
        Total 24 bytes

    General format of a packet:

      Byte/     0       |       1       |       2       |       3       |
         /              |               |               |               |
        |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
        +---------------+---------------+---------------+---------------+
       0/ HEADER                                                        /
        /                                                               /
        /                                                               /
        /                                                               /
        +---------------+---------------+---------------+---------------+
      24/ COMMAND-SPECIFIC EXTRAS (as needed)                           /
       +/  (note length in the extras length header field)              /
        +---------------+---------------+---------------+---------------+
       m/ Key (as needed)                                               /
       +/  (note length in key length header field)                     /
        +---------------+---------------+---------------+---------------+
       n/ Value (as needed)                                             /
       +/  (note length is total body length header field, minus        /
       +/   sum of the extras and key length body fields)               /
        +---------------+---------------+---------------+---------------+
        Total 24 bytes
 </pre>
 */
public abstract class BinaryCommonHeader implements ByteBean, IdentifyableOfInt {
    /**
	 * The following static constants are used for the binary protocol.
	 */
	public static final byte MAGIC_REQ = (byte) 0x80;
	public static final byte MAGIC_RESP = (byte) 0x81;
	public static final int F_COMPRESSED = 2;
	public static final int F_SERIALIZED = 8;

	public static final int STAT_NO_ERROR = 0x0000;
	public static final int STAT_KEY_NOT_FOUND = 0x0001;
	public static final int STAT_KEY_EXISTS = 0x0002;
	public static final int STAT_VALUE_TOO_BIG = 0x0003;
	public static final int STAT_INVALID_ARGUMENTS = 0x0004;
	public static final int STAT_ITEM_NOT_STORED = 0x0005;
	public static final int STAT_UNKNOWN_COMMAND = 0x0081;
	public static final int STAT_OUT_OF_MEMORY = 0x0082;

	public static final byte OPCODE_GET = (byte) 0x00;
	public static final byte OPCODE_SET = (byte) 0x01;
	public static final byte OPCODE_ADD = (byte) 0x02;
	public static final byte OPCODE_REPLACE = (byte) 0x03;
	public static final byte OPCODE_DELETE = (byte) 0x04;
	public static final byte OPCODE_INCREMENT = (byte) 0x05;
	public static final byte OPCODE_DECREMENT = (byte) 0x06;
	public static final byte OPCODE_QUIT = (byte) 0x07;
	public static final byte OPCODE_FLUSH = (byte) 0x08;
	public static final byte OPCODE_GETQ = (byte) 0x09;
	public static final byte OPCODE_NOOP = (byte) 0x0A;
	public static final byte OPCODE_VERSION = (byte) 0x0B;
	public static final byte OPCODE_GETK = (byte) 0x0C;
	public static final byte OPCODE_GETKQ = (byte) 0x0D;
	public static final byte OPCODE_APPEND = (byte) 0x0E;
	public static final byte OPCODE_PREPEND = (byte) 0x0F;
	public static final byte OPCODE_STAT = (byte) 0x10;

    @ByteField(index = 0,description = "Magic number identifying the package")
    private byte magic;

    @ByteField(index = 1,description = "Command code")
    private byte opCode;

    @ByteField(index = 2,description = "Length in bytes of the text key that follows the command extras")
    private short keyLength;

    @ByteField(index = 3,description = "Length in bytes of the command extras")
    private byte extrasLength;

    @ByteField(index = 4,description = "Reserved for future use")
    private byte dataType;

    @ByteField(index = 6,description = "Length in bytes of extra + key + value")
    private int totalBodyLength;

    @ByteField(index = 7,description = "Will be copied back to you in the response")
    private int opaque;

    @ByteField(index = 8,description = "Data version check")
    private long cas;

    public byte getMagic() {
        return magic;
    }

    public void setMagic(byte magic) {
        this.magic = magic;
    }

    public byte getOpCode() {
        return opCode;
    }

    public void setOpCode(byte opCode) {
        this.opCode = opCode;
    }

    public short getKeyLength() {
        return keyLength;
    }

    public void setKeyLength(short keyLength) {
        this.keyLength = keyLength;
    }

    public byte getExtrasLength() {
        return extrasLength;
    }

    public void setExtrasLength(byte extrasLength) {
        this.extrasLength = extrasLength;
    }

    public byte getDataType() {
        return dataType;
    }

    public void setDataType(byte dataType) {
        this.dataType = dataType;
    }

    public int getTotalBodyLength() {
        return totalBodyLength;
    }

    public void setTotalBodyLength(int totalBodyLength) {
        this.totalBodyLength = totalBodyLength;
    }

    public int getOpaque() {
        return opaque;
    }

    public void setOpaque(int opaque) {
        this.opaque = opaque;
    }

    public long getCas() {
        return cas;
    }

    public void setCas(long cas) {
        this.cas = cas;
    }

    public int	getIntIdentification(){
        return this.getOpaque();
    }

    @Override
    public String toString() {
        return "BinaryCommonHeader{" +
                "magic=" + magic +
                ", opCode=" + opCode +
                ", keyLength=" + keyLength +
                ", extrasLength=" + extrasLength +
                ", dataType=" + dataType +
                ", totalBodyLength=" + totalBodyLength +
                ", opaque=" + opaque +
                ", cas=" + cas +
                '}';
    }
}
